#include <iostream>
#include <climits>
#include <algorithm>
template <typename T>
struct Matrix{
int eN, vN;
T** data;
Matrix(int _vN): vN(_vN) {
data=new T*[this->vN];
for(int i=0; i<vN; ++i) data[i]=new T[this->vN];
}
Matrix(const Matrix& other){
this->vN=other.vN;
this->eN=other.eN;
this->data=new T*[this->vN];
for(int i=0; i<this->vN; ++i){
this->data[i]=new T[this->vN];
}
for(int i=0; i<this->vN; ++i){
for(int j=0; j<this->vN; ++j) this->data[i][j]=other.data[i][j];
}
}
~Matrix(){
for(int i=0; i<this->vN; ++i) delete[] this->data[i];
delete[] this->data;
}
Matrix& operator=(const Matrix& other){
this->vN=other.vN;
this->eN=other.eN;
for(int i=0; i<this->vN; ++i){
for(int j=0; j<this->vN; ++j){
this->data[i][j]=other[i][j];
}
}
return *this;
}
T* operator[](int ind) const {
return this->data[ind];
}
void makeD(T W[][3], int _eN){
this->eN=_eN;
for(int i=0; i<this->vN; ++i){
for(int j=0; j<this->vN; ++j){
if(i==j) this->data[i][j]=0;
else this->data[i][j]=INT_MAX;
}
}
for(int i=0; i<this->eN; ++i){
this->data[W[i][0]-1][W[i][1]-1]=W[i][2];
}
}
void print(void){
for(int i=0; i<this->vN; ++i){
for(int j=0; j<this->vN; ++j){
std::cout<<this->data[i][j]<<' ';
}
std::cout<<'\n';
}
std::cout<<std::endl;
}
};
template <typename T>
Matrix<T> FloydWarshall(const Matrix<T>& W){
int n=W.vN;
Matrix<T> D=W;
for(int k=0; k<n; ++k){
Matrix<T> tmpD(n);
for(int i=0; i<n; ++i){
for(int j=0; j<n; ++j){
if(D[i][k]==INT_MAX || D[k][j]==INT_MAX) tmpD[i][j]=D[i][j];
else tmpD[i][j]=std::min(D[i][j], D[i][k]+D[k][j]);
}
}
D=tmpD;
}
return D;
}
int main(void){
const int eN=9, vN=5;
int Edge[eN][3]={
{1, 2, 3}, {1, 3, 8}, {1, 5, -4},
{2, 4, 1}, {2, 5, 7}, {3, 2, 4},
{4, 1, 2}, {4, 3, -5}, {5, 4, 6}
};
Matrix<int> D0(vN);
D0.makeD(Edge, eN);
Matrix<int> Dn=FloydWarshall<int>(D0);
Dn.print();
return 0;
}